In [2]:
import pandas as pd
import numpy as np
import yfinance as yf
import random
from matplotlib import pyplot as plt
import seaborn as sns
import warnings
import secrets
import plotly.express as px
from tqdm import tqdm
from tqdm import tqdm
#warnings.simplefilter(action='ignore', category=FutureWarning)
Variables
In [3]:
TICKER="IWDA.AS"
NUMBER_OF_SIMULATIONS=1000
STARTING_CAPITAL = 10000
YEARS_OF_SIMULATION=30
In [4]:
YEARS_OF_SIMULATION=YEARS_OF_SIMULATION+1
Market_Days=253
df=yf.download(TICKER)["Adj Close"].pct_change(1).dropna()
[*********************100%%**********************] 1 of 1 completed
In [5]:
df.plot()
Out[5]:
<Axes: xlabel='Date'>
In [6]:
df
Out[6]:
Date
2009-09-28 0.000000
2009-09-29 0.000000
2009-09-30 0.000000
2009-10-01 0.000000
2009-10-02 0.000000
...
2023-11-06 -0.002663
2023-11-07 0.005862
2023-11-08 -0.003432
2023-11-09 0.004418
2023-11-10 -0.002393
Name: Adj Close, Length: 3619, dtype: float64
In [7]:
df_simulations=np.zeros((YEARS_OF_SIMULATION,NUMBER_OF_SIMULATIONS))
df_simulations[0,:]=STARTING_CAPITAL
for x in tqdm(range(0,NUMBER_OF_SIMULATIONS)):
for i in range(1,YEARS_OF_SIMULATION):
annual_change=1
for k in range(Market_Days):
annual_change=annual_change*(1+(secrets.choice(df.iloc[:])))
df_simulations[i,x]=annual_change*df_simulations[i-1,x]
df_simulations= pd.DataFrame(df_simulations)
df_simulations_1= pd.DataFrame(df_simulations)
0%| | 0/1000 [00:00<?, ?it/s]C:\Users\dadoi\anaconda3\Lib\random.py:374: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]` return seq[self._randbelow(len(seq))] 100%|██████████| 1000/1000 [03:17<00:00, 5.07it/s]
In [8]:
df_simulations_1
Out[8]:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | ... | 1.000000e+04 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 | 10000.000000 |
| 1 | 12374.356501 | 13557.505948 | 11085.935569 | 10717.395398 | 11124.749700 | 12813.332621 | 11454.969142 | 11003.642513 | 8275.682047 | 10140.584393 | ... | 9.800875e+03 | 10925.198767 | 14066.139619 | 11885.815598 | 12000.004278 | 15846.689896 | 10413.797090 | 8875.341269 | 10109.211586 | 10956.951002 |
| 2 | 11539.589159 | 17665.345757 | 10144.824103 | 12616.024598 | 8220.254846 | 11066.912276 | 11487.513001 | 10679.449962 | 9243.447317 | 9266.201665 | ... | 1.177905e+04 | 14716.757570 | 11988.455698 | 14666.496164 | 12039.188328 | 16439.406420 | 10494.849516 | 7135.823025 | 11140.330248 | 13584.603899 |
| 3 | 10663.110456 | 15148.147606 | 11369.266117 | 14899.379156 | 10302.282506 | 13448.384959 | 15389.673093 | 10961.094132 | 9973.075447 | 11718.735494 | ... | 1.456873e+04 | 17328.260156 | 14051.267794 | 16974.321044 | 12211.664021 | 19350.873050 | 9492.505918 | 7387.381321 | 13158.005874 | 19165.819743 |
| 4 | 13185.003651 | 13966.397720 | 11280.032386 | 15774.264644 | 12815.825197 | 13274.584608 | 13763.466519 | 12752.909080 | 10768.783615 | 13280.939593 | ... | 1.517157e+04 | 20876.728129 | 17442.722137 | 15661.186848 | 16177.353346 | 24012.404752 | 9416.364825 | 8552.320908 | 16247.936078 | 18332.073921 |
| 5 | 13001.493785 | 14876.114635 | 12620.891210 | 14286.397864 | 12302.783931 | 18834.487964 | 15717.915877 | 14411.447540 | 12062.020077 | 16960.350204 | ... | 2.261771e+04 | 24488.202096 | 20730.642049 | 20656.872967 | 18682.177989 | 22804.410842 | 9114.443936 | 8472.019752 | 16416.061259 | 13754.178342 |
| 6 | 10672.651285 | 14921.455402 | 13894.564717 | 21878.485631 | 15915.496614 | 18263.235511 | 20156.837837 | 13202.248298 | 15736.988127 | 18258.572083 | ... | 2.869943e+04 | 27198.024501 | 20724.295689 | 22895.436359 | 23488.522780 | 19042.192159 | 8684.891287 | 8444.235589 | 19547.101608 | 13823.547650 |
| 7 | 9749.141449 | 19528.075148 | 16993.790794 | 18197.334866 | 17889.470608 | 21714.543178 | 27182.058438 | 17545.942916 | 18993.350362 | 21400.485550 | ... | 4.150609e+04 | 29396.694633 | 22002.332919 | 22734.427439 | 28681.903623 | 21059.646453 | 9325.732670 | 8692.552470 | 24012.421921 | 15565.698173 |
| 8 | 10493.017905 | 17172.853087 | 23068.214673 | 21167.023219 | 14690.264338 | 20878.352218 | 25351.201797 | 21707.734837 | 22224.452167 | 21012.155492 | ... | 4.347877e+04 | 34204.078163 | 20988.091092 | 22727.261752 | 38918.199737 | 21469.058576 | 11113.124284 | 11036.250184 | 25155.445956 | 21147.094202 |
| 9 | 15296.890401 | 15359.713252 | 22684.061039 | 25456.991221 | 18570.297064 | 16691.004768 | 28632.490845 | 22735.377708 | 23308.663683 | 23175.075538 | ... | 7.165173e+04 | 40765.694809 | 16831.582938 | 24150.504205 | 40690.035033 | 21875.670342 | 13146.815249 | 15649.277902 | 25815.474790 | 21109.324894 |
| 10 | 14023.423952 | 17253.508925 | 30406.938019 | 29187.923253 | 16332.579239 | 22330.143295 | 34488.669152 | 22067.057462 | 24103.422524 | 18888.154864 | ... | 7.328605e+04 | 43433.704205 | 16693.528025 | 23135.356794 | 35987.964174 | 26889.475373 | 13907.601542 | 12397.070190 | 26166.213373 | 18407.755192 |
| 11 | 11757.069984 | 27081.672620 | 29864.875031 | 23523.429844 | 16743.671207 | 22539.015584 | 34360.661775 | 20239.248950 | 22989.124830 | 21907.136783 | ... | 9.816865e+04 | 37724.080038 | 21631.987010 | 29378.328770 | 29896.756276 | 29201.149457 | 14053.910406 | 12199.846707 | 26574.487423 | 22269.173763 |
| 12 | 15833.847325 | 28713.316163 | 26567.832553 | 28534.875908 | 16452.208243 | 28886.359214 | 37243.704646 | 21412.176161 | 23408.611344 | 31563.919894 | ... | 1.127641e+05 | 41150.894907 | 19169.826987 | 40323.378015 | 33017.602189 | 30377.675228 | 14582.275569 | 18544.725109 | 39191.195495 | 21084.367463 |
| 13 | 16768.436420 | 29735.642738 | 24150.531200 | 24373.618538 | 14661.893686 | 29075.843002 | 39769.700256 | 26143.738229 | 24915.863909 | 35272.303392 | ... | 1.222319e+05 | 56894.177327 | 20992.000671 | 38526.740471 | 34243.887992 | 43447.641967 | 16579.958454 | 25011.027662 | 49127.192568 | 25120.637017 |
| 14 | 15424.369586 | 36409.057757 | 26825.968595 | 30642.826976 | 13730.975926 | 35149.337182 | 39879.685587 | 44002.858770 | 28147.169547 | 32028.986088 | ... | 1.374079e+05 | 61149.381471 | 20344.559216 | 52388.227239 | 46015.716677 | 57878.415502 | 15135.420359 | 26782.915003 | 50450.959660 | 27412.671150 |
| 15 | 20062.405982 | 41194.826400 | 17933.256162 | 32708.415745 | 12764.627976 | 41187.206890 | 38694.176510 | 39376.787293 | 27214.947656 | 33878.389370 | ... | 1.513638e+05 | 64693.651085 | 23588.727807 | 53730.290800 | 50802.357460 | 95391.905565 | 17359.335480 | 37097.246609 | 48133.410581 | 25899.992404 |
| 16 | 19749.810890 | 43590.280621 | 18209.954340 | 33264.881522 | 11751.698971 | 50203.813382 | 44583.374209 | 43888.240716 | 29012.656577 | 35911.447986 | ... | 1.893603e+05 | 71152.851602 | 28120.013814 | 76436.940104 | 63484.327914 | 115818.510447 | 16114.663863 | 35159.916599 | 56208.072904 | 26289.607939 |
| 17 | 22722.327141 | 46526.365395 | 17180.168552 | 48170.974782 | 12655.758763 | 73566.924244 | 63128.667256 | 44225.364499 | 35008.926555 | 42888.322151 | ... | 2.088115e+05 | 83396.903412 | 38170.877837 | 101804.645142 | 73961.447977 | 144232.144280 | 22503.093466 | 32592.183897 | 56955.291981 | 36214.571729 |
| 18 | 23428.954453 | 50585.591712 | 25303.416468 | 64214.547380 | 15811.904122 | 64344.879132 | 66083.375168 | 48072.046560 | 43532.511591 | 40276.738040 | ... | 2.725110e+05 | 86948.797415 | 35878.622106 | 122316.947582 | 67567.209255 | 153512.105897 | 25627.722410 | 44545.559143 | 55285.703421 | 44151.334961 |
| 19 | 24845.265646 | 63169.120168 | 24244.432886 | 62733.042963 | 17167.202324 | 65208.367302 | 69620.518238 | 53466.759977 | 49973.344154 | 48079.087691 | ... | 4.000785e+05 | 113236.824698 | 45394.484183 | 133261.321989 | 63106.850320 | 195689.356243 | 28605.918489 | 55909.832936 | 50562.242521 | 48091.330212 |
| 20 | 24123.826380 | 77818.418952 | 28966.219143 | 58949.659556 | 25585.449980 | 113666.063005 | 85042.463402 | 64368.354467 | 46967.384939 | 79079.179552 | ... | 5.157540e+05 | 153240.117181 | 42595.132702 | 138066.807590 | 68117.252987 | 180307.741152 | 32645.605062 | 61806.359699 | 52860.118629 | 50316.061895 |
| 21 | 23813.083061 | 74112.860044 | 28001.546909 | 71691.371551 | 29395.187827 | 116885.148168 | 117740.722332 | 73866.516782 | 43612.148828 | 67403.339503 | ... | 5.909733e+05 | 186104.777778 | 47797.491551 | 130924.637354 | 71717.138540 | 154329.353008 | 47615.022551 | 69170.610730 | 73501.808786 | 70602.475876 |
| 22 | 34295.429578 | 87606.387715 | 36205.539691 | 82265.792113 | 36978.621875 | 134348.094817 | 132410.730725 | 72675.588813 | 49005.592252 | 56393.232602 | ... | 6.213856e+05 | 216028.512065 | 44622.797814 | 155728.433371 | 62603.610565 | 149957.563809 | 59932.877878 | 96047.468914 | 61025.025645 | 91314.193668 |
| 23 | 40448.361237 | 93358.203507 | 56150.354994 | 60628.441761 | 54793.426756 | 142276.753293 | 173265.666120 | 66271.332979 | 52004.772569 | 101048.064539 | ... | 8.941850e+05 | 242599.947563 | 63151.922901 | 145569.286089 | 62930.070402 | 185832.616512 | 55386.464078 | 112542.492437 | 75283.725068 | 132133.905373 |
| 24 | 58159.259358 | 83666.989029 | 53130.481861 | 83391.112565 | 45965.740131 | 202312.923636 | 224159.166588 | 63838.802544 | 48588.613367 | 107072.052978 | ... | 1.199984e+06 | 304108.688629 | 78510.695186 | 149072.309915 | 54058.446946 | 248442.316729 | 53080.079475 | 113068.758859 | 73620.166177 | 128588.989725 |
| 25 | 63205.858615 | 85268.775426 | 56611.435796 | 68284.217799 | 45357.508057 | 215925.096657 | 287895.455399 | 68347.905596 | 43064.521304 | 129597.043202 | ... | 1.300306e+06 | 284565.757952 | 89751.699266 | 138787.948752 | 55706.290540 | 252885.985260 | 51406.023813 | 202172.639276 | 77255.506565 | 118530.145033 |
| 26 | 63191.675886 | 82546.234917 | 62024.437510 | 92419.133675 | 47833.594673 | 236918.165131 | 310961.723479 | 94837.412955 | 45436.116006 | 124495.190280 | ... | 1.131026e+06 | 295485.579160 | 75359.141414 | 178400.935840 | 60938.192564 | 248465.703011 | 64112.484421 | 203288.246643 | 53558.704598 | 118207.810934 |
| 27 | 96040.973617 | 71093.749630 | 93374.722722 | 123511.976798 | 45645.953261 | 218096.092016 | 380057.812516 | 124597.850482 | 37480.672247 | 156224.294281 | ... | 1.325596e+06 | 376302.964808 | 78006.031984 | 222869.788751 | 89274.401213 | 276738.669836 | 69343.189403 | 238415.725748 | 53419.990603 | 108851.396732 |
| 28 | 99484.674404 | 74675.873923 | 106566.886231 | 136451.670006 | 44305.023570 | 253178.939365 | 328291.641093 | 128781.460951 | 50363.481681 | 216844.315735 | ... | 1.037930e+06 | 581727.232825 | 131677.297775 | 256662.502562 | 97454.679390 | 288458.725938 | 96928.801187 | 253709.370592 | 99897.249246 | 131877.051209 |
| 29 | 147720.678433 | 81027.883465 | 120483.084795 | 123897.283134 | 57834.463037 | 268951.500272 | 371582.398299 | 142311.658856 | 37997.862425 | 223616.672916 | ... | 1.000407e+06 | 757212.345650 | 141721.219233 | 304062.467574 | 123447.184444 | 256886.776871 | 109171.829236 | 215792.851824 | 127871.989485 | 138561.355795 |
30 rows × 1000 columns
In [9]:
df_simulations=df_simulations_1
df_simulations.iloc[YEARS_OF_SIMULATION-1]
Out[9]:
0 147720.678433
1 81027.883465
2 120483.084795
3 123897.283134
4 57834.463037
...
995 256886.776871
996 109171.829236
997 215792.851824
998 127871.989485
999 138561.355795
Name: 29, Length: 1000, dtype: float64
In [10]:
quantile=df_simulations.iloc[YEARS_OF_SIMULATION-1].quantile([0.1,0.9])
quantile=list(quantile)
print(quantile)
df_simulations_purged=df_simulations[df_simulations.columns[ df_simulations.max() < quantile[1]]]
df_simulations_purged=df_simulations_purged[df_simulations_purged.columns[ df_simulations_purged.max() > quantile[0]]]
[72428.53043444845, 638093.5202050379]
In [31]:
df_simulations_purged.plot(legend=None,logy=False,fontsize=20,figsize=(25,15),title=f"Simulation of {NUMBER_OF_SIMULATIONS} portfolios")
Out[31]:
<Axes: title={'center': 'Simulation of 1000 portfolios'}>
In [39]:
df_simulations_purged.iloc[YEARS_OF_SIMULATION-1].plot.density(figsize=(25,15),fontsize=20, xlim=(-100000,900000))
Out[39]:
<Axes: ylabel='Density'>
In [77]:
top_25 =[]
low_25 =[]
median=[]
for i in range(0,YEARS_OF_SIMULATION):
top_25.append(df_simulations.iloc[i].quantile(0.75))
low_25.append(df_simulations.iloc[i].quantile(0.25))
median.append(df_simulations.iloc[i].median())
columns=["top_25","median","bottom_25"]
df_statistics=pd.DataFrame(list(zip(top_25,median,low_25)),columns=columns)
df_statistics
Out[77]:
| top_25 | median | bottom_25 | |
|---|---|---|---|
| 0 | 10000.000000 | 10000.000000 | 10000.000000 |
| 1 | 12453.746675 | 11086.631807 | 10085.954403 |
| 2 | 14182.914367 | 12349.502709 | 10631.807076 |
| 3 | 16265.828340 | 13676.866873 | 11360.205672 |
| 4 | 19016.815440 | 15271.882868 | 12205.819771 |
| 5 | 21221.611492 | 16781.337904 | 13454.873305 |
| 6 | 24093.125953 | 18902.502176 | 14360.431095 |
| 7 | 27128.493970 | 20846.316066 | 15651.172380 |
| 8 | 30702.934676 | 23069.338128 | 17268.554051 |
| 9 | 34984.183950 | 25619.245356 | 18552.889874 |
| 10 | 39193.842413 | 28707.467827 | 20211.645260 |
| 11 | 44828.092619 | 32218.249955 | 22553.346988 |
| 12 | 50578.396654 | 35609.239111 | 24380.729511 |
| 13 | 57280.792681 | 39155.785346 | 26353.231912 |
| 14 | 63788.019734 | 42533.487198 | 28256.595131 |
| 15 | 73197.657219 | 47828.788282 | 32551.270061 |
| 16 | 81330.845703 | 53038.822240 | 35179.838074 |
| 17 | 92475.526587 | 60229.665425 | 38625.275318 |
| 18 | 106480.986472 | 66780.059431 | 41721.730516 |
| 19 | 117630.223068 | 73226.268865 | 46070.457748 |
| 20 | 132094.022793 | 80280.926615 | 50305.702845 |
| 21 | 153627.865288 | 90449.864377 | 55026.513621 |
| 22 | 169089.738427 | 102146.586530 | 60997.078189 |
| 23 | 190754.891439 | 113104.485180 | 66167.282463 |
| 24 | 216307.364736 | 122651.236030 | 73165.231305 |
| 25 | 238743.393285 | 133896.823289 | 80210.081170 |
| 26 | 274768.827974 | 149632.402758 | 86674.513610 |
| 27 | 298891.502910 | 168369.209694 | 96854.158847 |
| 28 | 342318.765902 | 189051.423382 | 107963.030337 |
| 29 | 379628.240161 | 212508.098422 | 119105.072557 |
In [85]:
ax= df_statistics.plot(legend=None,logy=False,fontsize=20,figsize=(25,15),linewidth=4,color="black",title=f"Simulation of {NUMBER_OF_SIMULATIONS} portfolios")
ax.fill_between(df_statistics.index,df_statistics['top_25'], df_statistics['median'],color="green")
ax.fill_between(df_statistics.index,df_statistics['median'],df_statistics['bottom_25'] ,color="red")
Out[85]:
<matplotlib.collections.PolyCollection at 0x22c335ebc90>
In [84]:
[NbConvertApp] Converting notebook Portfolio1.ipynb to html [NbConvertApp] WARNING | Alternative text is missing on 4 image(s). [NbConvertApp] Writing 2712985 bytes to Portfolio1.html
In [86]:
import plotly.express as px
fig = px.scatter(x=[0, 1, 2, 3, 4], y=[0, 1, 4, 9, 16])
fig.show()
In [ ]:
!jupyter nbconvert --to html Portfolio1.ipynb
In [ ]: